﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Threading;
using System.Windows.Forms;
using System.IO;
using HtmlAgilityPack;

namespace GetFilmInfo
{
    public partial class Form1 : Form
    {
        private Thread thrHTML;
        private List<FilmInfo> oList;
        private int iIndex = 0;
        public Form1()
        {
            InitializeComponent();
        }

        private void BtOpenFile_Click(object sender, EventArgs e)
        {
            OpenFileDialog openFile = new OpenFileDialog();
            openFile.Filter = @"txt file|*.txt";
            if (openFile.ShowDialog() == DialogResult.OK)
            {
                LbLink.Items.Clear();
                txtFile.Text = openFile.FileName;
                StreamReader reader = new StreamReader(openFile.FileName);

                while (reader.Peek() >= 0)
                {
                    string s = reader.ReadLine();
                    if (s.Trim() != "")
                    {
                        LbLink.Items.Add(s);
                    }
                }
            }
        }

        private void BtGo_Click(object sender, EventArgs e)
        {
            if (LbLink.Items.Count <= 0) return;
            if (oList != null && oList.Count > 0) oList.Clear();
            iIndex = 0;
            thrHTML = new Thread(GetHTML);
            thrHTML.Start();
        }

        private void GetHTML()
        {
            string sAddress = LbLink.Items[iIndex].ToString();
            SetIndex(LbLink,iIndex);
            if (sAddress.ToLower().StartsWith("http://") == false && sAddress.ToLower().StartsWith("https://") == false) sAddress = "http://" + sAddress;
            string sHTML = GetCodeHTML(sAddress);
            if (sHTML != "")
            {
                HtmlAgilityPack.HtmlDocument doc = new HtmlAgilityPack.HtmlDocument();
                doc.LoadHtml(sHTML);
                string sName = GetName(doc);
                string sYear = GetYear(doc);
                string sGenre = GetGenre(doc);
                string sRuntime = GetRuntime(doc);
                string sDirector = GetDirector(doc);
                string sRating = GetRating(doc);
                string sCast = GetCast(doc);
                string sKeywords = GetKeywords(doc);
                string sPlot = GetPlot(doc);

                if (sName != "")
                {
                    if(oList == null) oList = new List<FilmInfo>();
                    FilmInfo info = new FilmInfo()
                        {
                            ID = GetID(sAddress),
                            Name = sName,
                            Year = sYear,
                            Genre = sGenre,
                            Runtime = sRuntime,
                            Director = sDirector,
                            Rating = sRating,
                            Cast = sCast,
                            Keywords = sKeywords,
                            Plot = sPlot
                        };
                    oList.Add(info);
                }
            }

            if (iIndex < LbLink.Items.Count - 1)
            {
                iIndex++;
                thrHTML = new Thread(GetHTML);
                thrHTML.Start();
            }
        }

        private void SetIndex(ListBox obj, int index)
        {
            if (InvokeRequired)
            {
                this.Invoke((MethodInvoker)delegate() { SetIndex(obj, index); });
                return;
            }
            obj.SelectedIndex = index;
        }

        private static string GetCodeHTML(string Url)
        {
            try
            {
                HttpWebRequest myRequest = (HttpWebRequest)WebRequest.Create(Url);
                myRequest.Method = "GET";
                WebResponse myResponse = myRequest.GetResponse();
                StreamReader sr = new StreamReader(myResponse.GetResponseStream(), System.Text.Encoding.UTF8);
                string result = sr.ReadToEnd();
                sr.Close();
                myResponse.Close();
                return result;
            }
            catch (Exception)
            {
                return "";
            }
        }

        private string GetID(string s)
        {
            if (s.StartsWith("http://imdb.com/title/"))
            {
                string[] arr = s.Split('/');
                return arr[4];
            }
            return "";
        }

        //Name
        private static string GetName(HtmlAgilityPack.HtmlDocument doc)
        {
            List<HtmlNode> oNodes = null;
            oNodes = (from HtmlNode node in doc.DocumentNode.SelectNodes("//span")
                      where node.Name == "span"
                      && node.GetAttributeValue("class", "") == "itemprop"
                      select node).ToList();
            if (oNodes != null)
                foreach (HtmlNode node in oNodes)
                {
                    return node.InnerText;
                }
            return "";
        }

        //year
        private static string GetYear(HtmlAgilityPack.HtmlDocument doc)
        {
            List<HtmlNode> oNodes = null;
            oNodes = (from HtmlNode node in doc.DocumentNode.SelectNodes("//a")
                      where node.Name == "a"
                      && node.GetAttributeValue("href", "").StartsWith("/year/")
                      select node).ToList();
            if (oNodes != null)
                foreach (HtmlNode node in oNodes)
                {
                    return node.InnerText;
                }
            return "";
        }

        //Genre
        private static string GetGenre(HtmlAgilityPack.HtmlDocument doc)
        {
            List<HtmlNode> oNodes = null;
            oNodes = (from HtmlNode node in doc.DocumentNode.SelectNodes("//span")
                      where node.Name == "span"

                            && node.GetAttributeValue("itemprop", "") == "genre"
                            && node.Attributes["class"].Value == "itemprop"
                      select node).ToList();
            if (oNodes != null)
            {
                string sNode = "";
                foreach (HtmlNode node in oNodes)
                {
                    sNode += sNode != "" ? ", " + node.InnerText : node.InnerText;
                }
                return sNode;
            }
            return "";
        }

        //Runtime
        private static string GetRuntime(HtmlAgilityPack.HtmlDocument doc)
        {
            List<HtmlNode> oNodes = null;
            oNodes = (from HtmlNode node in doc.DocumentNode.SelectNodes("//time")
                      where node.Name == "time"
                            && node.GetAttributeValue("itemprop", "") == "duration"
                      select node).ToList();
            if (oNodes != null)
            {
                foreach (HtmlNode node in oNodes)
                {
                    return node.InnerText.Trim();
                }
            }
            return "";
        }

        //Director
        private static string GetDirector(HtmlAgilityPack.HtmlDocument doc)
        {
            List<HtmlNode> oNodes = null;
            oNodes = (from HtmlNode node in doc.DocumentNode.SelectNodes("//span")
                      where node.Name == "span"
                            && node.GetAttributeValue("itemprop", "") == "name"
                            && node.Attributes["class"].Value == "itemprop"
                            && node.ParentNode.ParentNode.GetAttributeValue("itemprop", "") == "director"
                      select node).ToList();
            if (oNodes != null)
            {
                string sNode = "";
                foreach (HtmlNode node in oNodes)
                {
                    sNode += sNode != "" ? "," + node.InnerText : node.InnerText;
                }
                return sNode;
            }
            return "";
        }

        //Rating
        private static string GetRating(HtmlAgilityPack.HtmlDocument doc)
        {
            List<HtmlNode> oNodes = null;
            oNodes = (from HtmlNode node in doc.DocumentNode.SelectNodes("//div")
                      where node.Name == "div"
                            && node.GetAttributeValue("itemprop", "") == "titlePageSprite star-box-giga-star"
                      select node).ToList();
            if (oNodes != null)
            {
                foreach (HtmlNode node in oNodes)
                {
                    return node.InnerText;
                }
            }
            return "";
        }

        //Cast
        private static string GetCast(HtmlAgilityPack.HtmlDocument doc)
        {
            List<HtmlNode> oNodes = null;
            oNodes = (from HtmlNode node in doc.DocumentNode.SelectNodes("//span")
                      where node.Name == "span"
                            && node.GetAttributeValue("itemprop", "") == "name"
                            && node.Attributes["class"].Value == "itemprop"
                            && node.ParentNode.ParentNode.GetAttributeValue("itemprop", "") == "actors"
                      select node).ToList();
            if (oNodes != null)
            {
                foreach (HtmlNode node in oNodes)
                {
                    return node.InnerText;
                }
            }
            return "";
        }

        //Keywords
        private static string GetKeywords(HtmlAgilityPack.HtmlDocument doc)
        {
            List<HtmlNode> oNodes = null;
            oNodes = (from HtmlNode node in doc.DocumentNode.SelectNodes("//span")
                      where node.Name == "span"
                            && node.GetAttributeValue("itemprop", "") == "keywords"
                      select node).ToList();
            if (oNodes != null)
            {
                string sNode = "";
                foreach (HtmlNode node in oNodes)
                {
                    sNode += sNode != "" ? "," + node.InnerText : node.InnerText;
                }
                return sNode;
            }
            return "";
        }

        //Plot
        private static string GetPlot(HtmlAgilityPack.HtmlDocument doc)
        {
            List<HtmlNode> oNodes = null;
            oNodes = (from HtmlNode node in doc.DocumentNode.SelectNodes("//p")
                      where node.Name == "p"
                            && node.GetAttributeValue("itemprop", "") == "description"
                      select node).ToList();
            if (oNodes != null)
            {
                foreach (HtmlNode node in oNodes)
                {
                    return node.InnerText;
                }
            }
            return "";
        }
    }
}
